# encoding=utf-8
# cosine 2010/9/20

"""
基于sqlmap的banner解析模块

"""

import sys
import urllib2
from headers import headersParser

class ServerInfo():
	"""用类实例方式来保存解析结果"""
	def __init__(self,**kargs):
		self.name = self.version = ''
		self.major = self.minor = 0
		self.apptype = ''
		for item,value in kargs.items():
			setattr(self,item,value)
		if self.apptype =='os':
			if not hasattr(self,'series'):
				self.series = ''
			if not hasattr(self,'codename'):
				self.codename = ''
			if not hasattr(self,'patch'):
				self.patch = ''

def parse_instance(headers):
	"""
	appscan直接调用的接口
	其他说明：app_info 可能有多个，os_info只取每项第一个
	"""
	return_dict = {'technology':None,'webserver':None,'os':None}
	bannerinfo = get_bannerinfo(headers)

	technologys = bannerinfo.get('technology')
	if technologys:
		for technology in technologys:
			if technology.find(':')>=0:
				name,version = technology.split(':')
			else:
				name,version = technology,''
			return_dict['technology'] = ServerInfo(name=name,version=version,apptype = 'technology')
			break

	webservers = bannerinfo.get('webserver')
	if webservers:
		for webserver in webservers:
			if webserver.find(':')>=0:
				name,version = webserver.split(':')
			else:
				name,version = webserver,''
			return_dict['webserver'] = ServerInfo(name=name,version=version,apptype = 'server')
			break

	os_info = ServerInfo(apptype = 'os')
	if bannerinfo.has_key('type'):
		os_info.name = list(bannerinfo['type'])[0]
		if bannerinfo.has_key('distrib'): # os型号
			os_info.series = list(bannerinfo['distrib'])[0]
		if bannerinfo.has_key('release'): # os版本号
			os_info.ver= list(bannerinfo['release'])[0]
		if bannerinfo.has_key('codename'): # os版本
			os_info.codename = list(bannerinfo['distrib'])[0]
		if bannerinfo.has_key('sp'): # os版本
			os_info.patch= list(bannerinfo['sp'])[0]
		return_dict['os'] = os_info

	return return_dict


######################################################################
def get_bannerinfo(headers):
	"""获取指定headers解析后的bannerinfo
	如：
	www.knownsec.com
	{'distrib': set([u'CentOS']), 'release': set([u'4.4', u'4.3']), 'webserver': set([u'Apache:2.0.52']), 'type':set([u'Linux'])}

	"""
	bannerinfo = {}
	headersParser(headers,bannerinfo)
	return bannerinfo

def parse(headers):
	"""
	返回值样例：
	www.discuz.net
	{'os': {'series': u'', 'codename': u'', 'version': u'', 'name': u'Linux'}, 'webserver': {'version': u'0.7.67', 'name': u'Nginx'}, 'technology': {'version': u'5.2.10', 'name': u'PHP'}}
	
	www.knownsec.com
	{'os': {'series': u'CentOS', 'version': u'4.4', 'name': u'Linux'}, 'webserver': {'version': u'2.0.52', 'name': u'Apache'}, 'technology': None}

	www.qq.com
	{'os': {'series': u'', 'codename': u'', 'version': u'', 'name': u'Linux'}, 'webserver': {'version': u'0.6.39', 'name': u'Nginx'}, 'technology': None}
	
	
	"""
	return_dict = {'technology':None,'webserver':None,'os':None}
	bannerinfo = get_bannerinfo(headers)
	technologys = bannerinfo.get('technology')
	if technologys:
		for technology in technologys:
			if technology.find(':')>=0:
				name,version = technology.split(':')
			else:
				name,version = technology,''
			return_dict['technology'] = {'name':name,'version':version}
			break
				
	webservers = bannerinfo.get('webserver')
	if webservers:
		for webserver in webservers:
			if webserver.find(':')>=0:
				name,version = webserver.split(':')
			else:
				name,version = webserver,''
			return_dict['webserver'] = {'name':name,'version':version}
			break

	os_info = {}
	if bannerinfo.has_key('type'):
		os_info['name'] = list(bannerinfo['type'])[0]
		if bannerinfo.has_key('distrib'): # os型号
			os_info['series'] = list(bannerinfo['distrib'])[0]
		if bannerinfo.has_key('release'): # os版本号
			os_info['version'] = list(bannerinfo['release'])[0]
		if bannerinfo.has_key('codename'): # os版本
			os_info['codename'] = list(bannerinfo['distrib'])[0]	
		if bannerinfo.has_key('sp'): # os版本
			os_info['patch'] = list(bannerinfo['sp'])[0]
		return_dict['os'] = os_info
	
	return return_dict

	
if __name__=='__main__':
	try:
		url = sys.argv[1]
	except:
		print 'usage: pythn finger.py http://www.knownsec.com/'
		sys.exit(0)
	req = urllib2.urlopen(url)
	headers = req.headers.dict
	print '------------- <header info> -------------'
	print headers
	bannerinfo =  get_bannerinfo(headers)
	print '------------- <banner info> -------------'
	print bannerinfo
	print '------------- <return info> -------------'
	print parse(headers)

